package com.tunnel.service.proxy;

import cn.hutool.json.JSONUtil;
import com.tunnel.common.config.client.ClientConfig;

import com.tunnel.common.config.client.ProxyClientConfig;

import com.tunnel.common.protocol.Protocol;
import com.tunnel.common.protocol.ProtocolType;
import com.tunnel.common.util.SequenceUtil;
import com.tunnel.service.cache.ResultCache;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.*;
import io.netty.util.CharsetUtil;

import java.util.*;

/**
 * 服务端持有的客户端数据信息
 */
public class ProxyService {

    public static Map<String, ClientConfig> configMap = new HashMap<>();
    public static Map<String, ChannelHandlerContext> map = new HashMap<>();

    /**
     * 客户端注册
     */
    public static void registerClient(ChannelHandlerContext ctx, Protocol protocol) {
        long sequenceId = protocol.getSequenceId();
        System.out.println("sequenceId:" + sequenceId);
        int length = protocol.getLength();
        System.out.println("length:" + length);

        String bodyStr = protocol.getBody();
        ClientConfig clientConfig = JSONUtil.toBean(bodyStr, ClientConfig.class);
        String clientKey = clientConfig.getKey();
        // TODO 可以优化成一种算法加密，先明文
        if (!clientKey.equals("123")) {
            System.out.println("当前验证不过同");
            return;
        }
        String clientName = clientConfig.getClientName();
        // 注册当前的客户端配置
        configMap.put(clientName, clientConfig);
        // 注册当前的通道
        map.put(clientName, ctx);
    }

    /**
     * 数据传输
     */
    public static void transferData(ChannelHandlerContext ctx, FullHttpRequest request) {
        // 通过标识符号进行查询通道
        String clientName = request.uri().split("/")[1];
        String proxyName = request.uri().split("/")[2];
        ProxyClientConfig currentConfig = new ProxyClientConfig();
        // 通过前缀先定为到当前客户端的配置
        for (ProxyClientConfig config : configMap.get(clientName).getProxyConfigs()) {
            // 找到当前配置的具体代理客户端转发的信息
            if (config.getName().equals(proxyName)) {
                // 找到对应的通道，进行数据传输
                currentConfig = config;
                break;
            }
        }
        if (Objects.isNull(currentConfig)) {
            System.out.println("传输失败，当前客户端关闭");
            // 处理请求并发送响应
            FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
            response.content().writeBytes(Unpooled.copiedBuffer("验证失败", CharsetUtil.UTF_8));
            ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
        }
        // 获取客户端的通道
        ChannelHandlerContext clientCtx = map.get(clientName);
        // 获取请求方法
        HttpMethod method = request.method();
        // 获取请求 URI,因为我们在pc端加了前缀，这里需要去除掉，否则mvc接口没有办法识别
        String uri = request.uri();
        // 获取 HTTP 版本
        HttpVersion version = request.protocolVersion();
        // 构建请求行
        StringBuilder body = new StringBuilder();
        body.append(method).append(" ").append(uri).append(" ").append(version).append("\r\n");

        // 获取请求头
        HttpHeaders headers = request.headers();
        for (String name : headers.names()) {
            for (String value : headers.getAll(name)) {
                body.append(name).append(": ").append(value).append("\r\n");
            }
        }
        // 添加空行分隔请求头和请求体
        body.append("\r\n");
        // 获取请求体内容
        ByteBuf content = request.content();
        String contentString = content.toString(CharsetUtil.UTF_8);
        body.append(contentString);

        // 输出原始报文
        System.out.println("原始报文: \n" + body.toString());
        Protocol protocol = new Protocol();
        protocol.setCommonType(ProtocolType.TRANSFER);
        protocol.setSequenceId(SequenceUtil.getSequenceId());
        protocol.setBody(body.toString());
        protocol.setLength(body.toString().getBytes().length);

        clientCtx.channel().writeAndFlush(protocol);
        // 通过结果集来判断是否接收到结果，有结果就返回前端
        while (true){
            Protocol rpcProtocol = ResultCache.resMap.get(protocol.getSequenceId());
            if (rpcProtocol!=null){
                // 证明有返回参数
                // 响应体
                // response_message(ctx);
                // 响应体
                String[] split = rpcProtocol.getBody().split("\r\n");
                // 定为到响应头和响应内容body
                int index = 0;
                String responseBody = "Hello, World!";
                for (String s : split){
                    index++;
                    if (s.equals("")){
                        break;
                    }
                }
                responseBody = split[index];
                // 构建HTTP响应
                FullHttpResponse response = new DefaultFullHttpResponse(
                        HttpVersion.HTTP_1_1,
                        HttpResponseStatus.OK,
                        Unpooled.copiedBuffer(responseBody, CharsetUtil.UTF_8)
                );

                // 设置响应头
                response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain; charset=UTF-8");
                response.headers().set(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());

                // 如果是HTTP/1.1且请求头中有Connection: keep-alive，则保持连接
                if (HttpUtil.isKeepAlive(request)) {
                    response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
                }

                // 发送响应
                ctx.writeAndFlush(response);
                break;
            }
        }

    }

    /**
     * 关闭
     */
    public static void closeClient() {

    }

    /**
     * 心跳检测
     */
    public static void heartbeat(ChannelHandlerContext ctx, Protocol msg) {
       String heartbeat = msg.getBody();
       System.out.println("收到客户端心跳：" + heartbeat);
    }
}
